package example;

import java.util.ArrayList;

import optimization.ConditionFieldIndex;


public class MergeJoin {
	
	public ArrayList<Tuples> output = new ArrayList<Tuples> ();
	int lindex = 0;
	int rindex = 0;
	public ArrayList<Tuples> merge(ArrayList<Tuples> left,ArrayList<Tuples>  right, ConditionFieldIndex cfi) {
		System.out.println("Joining "+ left.size() + " with " + right.size());
		util.selectionSort(left);
		util.selectionSort(right);
		int conditionCheck = 0;
		if(cfi.type==1)
		try {
			while (lindex <left.size() &&  rindex <right.size())
	        {
				Tuples ltuples = left.get(lindex);
				Tuples rtuples = right.get(rindex);
					conditionCheck = this.checkCond(ltuples,rtuples,  cfi);
	            if (conditionCheck==0)
	            {
	            	this.mergeTup(left,right,cfi);
	            }
	            //left > right
	            else if (conditionCheck> 0)
	                rindex ++;
	            else if (conditionCheck <0)
	                lindex++;
	        }
			this.printTup();
		}
		catch(Exception e) {
			
		}
		//cartesian
		else {
			this.nestedLoop( left, right, cfi);
		}
		return output;
		
	}
	public ArrayList<Tuples> nestedLoop(ArrayList<Tuples> left,ArrayList<Tuples>  right, ConditionFieldIndex cfi) {
		int conditionCheck = 0;
		Tuples otuples = new Tuples();
		if(cfi.type==0)
		try {
			for(int i=0;i<left.size();i++)
	        {
				Tuples ltuples = left.get(i);
				for(int j=0;j<right.size();j++) {
					Tuples rtuples = right.get(j);
					otuples = concatTup(left.get(i),right.get(j));
					output.add(otuples);
				}
	        }
			this.printTup();
		}
		catch(Exception e) {
			
		}
		//cartesian
		else {
			this.nestedLoop( left, right, cfi);
		}
		return output;
	}
	private int checkCond(Tuples ltuples, Tuples rtuples, ConditionFieldIndex cfi) {
		// TODO Auto-generated method stub
		int check=0;
		int leftPos = cfi.l_hsIndex;
		int rightPos = cfi.r_hsIndex;
		if (cfi.type ==0) check = 0;
		else {
			if (ltuples.getKey(leftPos).toUpperCase().compareTo(rtuples.getKey(rightPos).toUpperCase()) >0)
				check =  1;
			if (ltuples.getKey(leftPos).toUpperCase().compareTo(rtuples.getKey(rightPos).toUpperCase()) <0)
				check = -1;
			else check  = 0;
		}
		return check;
	}
	public void printTup(){
		System.out.println("printing tuples "+output.size());
		try {
			for(int i=0;i<=output.size();i++) {
				Tuples t = new Tuples();
				t = output.get(i);
				try {
					for(int j=0;j<=t.tups.size();j++) {
						System.out.print(t.tups.get(j)+"; ");
					}
				}
				catch(Exception e){					
				}
				System.out.println(" ");
			}
		}
		catch(Exception e) {			
		}
	}
	public Tuples mergeTup(ArrayList<Tuples> left,ArrayList<Tuples>  right, ConditionFieldIndex joinNodeCondition ) {
		Tuples otuples = new Tuples();
		try{
			int rightIndex = rindex; 
			Tuples ltuples = left.get(lindex);
			Tuples rtuples = right.get(rindex);
			int conditionCheck = this.checkCond(ltuples,rtuples,joinNodeCondition);
			while(lindex < left.size() && (conditionCheck==0) ) {
				ltuples = left.get(lindex);
				rtuples = right.get(rindex);
				conditionCheck = this.checkCond(ltuples,rtuples,joinNodeCondition);
				while(rightIndex < right.size() && (conditionCheck==0) ) {
					otuples = concatTup(left.get(lindex),right.get(rightIndex));
					output.add(otuples);
					rightIndex++;
				}
				lindex++;
			}
		}
		catch(Exception e) {
			
		}
		return otuples;
	}
	private Tuples concatTup(Tuples tuples1, Tuples tuples2) {
		// TODO Auto-generated method stub
		Tuples o = new Tuples();
		try {
		for(int i=0;i<=tuples1.tups.size();i++)
			o.tups.add(tuples1.tups.get(i));
		}
		catch (Exception e) {
			
		}
		int j = 0;
		try {
			for(int i=0;i<=tuples1.tups.size();i++) {
					o.tups.add(tuples2.tups.get(i));			
			}
		}
		catch (Exception e) {
		}
		return o;
	}
	

}
